#include "libmp3lame/src/lame.h"
#include "libmp3lame/src/com_qd_videorecorder_util_SimpleLame.h"
#include <stdlib.h>
#include <jni.h>
#include <stdio.h>
#include <android/log.h>
#define LOG_TAG   "libmad"
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

static lame_global_flags *glf = NULL;

JNIEXPORT void JNICALL Java_com_myaudio_mange_SimpleLame_init(
		JNIEnv *env, jclass cls, jint inSamplerate, jint outChannel,
		jint outSamplerate, jint outBitrate, jint quality) {
	if (glf != NULL) {
		lame_close(glf);
		glf = NULL;
	}
	glf = lame_init();
	lame_set_in_samplerate(glf, inSamplerate);
	lame_set_num_channels(glf, outChannel);
	lame_set_out_samplerate(glf, outSamplerate);
	lame_set_brate(glf, outBitrate);
	lame_set_quality(glf, quality);
	lame_init_params(glf);
}

JNIEXPORT jint JNICALL Java_com_myaudio_mange_SimpleLame_encode(
		JNIEnv *env, jclass cls, jshortArray buffer_l, jshortArray buffer_r,
		jint samples, jbyteArray mp3buf) {
	jshort* j_buffer_l = (*env)->GetShortArrayElements(env, buffer_l, NULL);

	jshort* j_buffer_r = (*env)->GetShortArrayElements(env, buffer_r, NULL);

	const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
	jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);

	int result = lame_encode_buffer(glf, j_buffer_l, j_buffer_r, samples,
			j_mp3buf, mp3buf_size);

	(*env)->ReleaseShortArrayElements(env, buffer_l, j_buffer_l, 0);
	(*env)->ReleaseShortArrayElements(env, buffer_r, j_buffer_r, 0);
	(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);

	return result;
}

JNIEXPORT jint JNICALL Java_com_myaudio_mange_SimpleLame_flush(
		JNIEnv *env, jclass cls, jbyteArray mp3buf) {
	const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
	jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);

	int result = lame_encode_flush(glf, j_mp3buf, mp3buf_size);

	(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);

	return result;
}

JNIEXPORT void JNICALL Java_com_myaudio_mange_SimpleLame_close(
		JNIEnv *env, jclass cls) {
	lame_close(glf);
	glf = NULL;
}

char* Jstring2CStr(JNIEnv* env, jstring jstr)
{
	char* rtn = NULL;  //rtn 一块能够存放char类型内存的首地址
	// 找到 jvm里面 String类
	jclass clsstring = (*env)->FindClass(env, "java/lang/String");
	// 创建一个jstring的字符串内容 GB2312
	jstring strencode = (*env)->NewStringUTF(env, "UTF-8");
	// 寻找 String类的一个方法 getBytes   getBytes方法的参数 Ljava/lang/String;
	// getBytes 方法的返回值 [B
	jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
			"(Ljava/lang/String;)[B");
	// "String".getBytes("GB2312");
	jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
			strencode);
	//获取到barr的长度
	jsize alen = (*env)->GetArrayLength(env, barr);
	//获取到的jbyte 数据放入到以ba 为开始地址的内存空间中
	jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
	if (alen > 0)
	{
		rtn = (char*) malloc(alen + 1);        //new   char[alen+1]; "\0" 字符串的结束
		//内存拷贝的操作 ,
		memcpy(rtn, ba, alen);
		//给字符数组最后一个元素  表示字符串结束
		rtn[alen] = 0;
	}
	(*env)->ReleaseByteArrayElements(env, barr, ba, 0);
	return rtn;
}

JNIEXPORT jint JNICALL Java_com_myaudio_mange_SimpleLame_convert
(JNIEnv * env, jobject obj, jstring input, jstring output, jint channel , jint sample) {
			
	//1.找到java代码native方法所在的字节码文件  
	//jclass (*FindClass)(JNIEnv*, const char*);  
	jclass clazz = (*env)->FindClass(env, "com/myaudio/mange/AudioManager");  
	if(clazz == 0){  
		LOGE("find class error");  
		return;  
	}  
	LOGE("find class");  
	//2.找到class里面对应的方法  
	// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);  
	jmethodID convert = (*env)->GetMethodID(env,clazz,"covertCallBack","(I)I");  
	if(convert == 0){  
		LOGE("find convert error");  
		return;  
	}  
	LOGE("find convert");  
	 jobject dpobj= (*env)->AllocObject(env,clazz);
	jint count = 0;

	//把java的string类型的文件转化成c能识别的char 字符串
	char* inputfile = Jstring2CStr(env,input);
	char* outputfile = Jstring2CStr(env,output);

	FILE *pcm = fopen(inputfile, "rb");
	FILE *mp3 = fopen(outputfile, "wb");
	int read, write;
	const int PCM_SIZE = 8192;
	const int MP3_SIZE = 8192;
	short int pcm_buffer[PCM_SIZE*2];
	unsigned char mp3_buffer[MP3_SIZE];
	//初始化lame解码器
	lame_t lame = lame_init();
	// 设置音频的采样率
//	lame_set_in_samplerate(lame, 44100);
	lame_set_in_samplerate(lame, 22050);
	lame_set_out_samplerate(lame, 44100);
	//lame_set_in_samplerate(lame, 4000);
//	lame_set_in_samplerate(lame, sample);
	// 设置lame编码器的声道
//	lame_set_num_channels(lame,2);
	lame_set_num_channels(lame,1);
//	lame_set_num_channels(lame, channel);
	// vbr 设置采样压缩格式,设置后音频时长部分机型不准确
	//lame_set_VBR(lame, vbr_default);
	//16kBps
	lame_set_brate(lame,16);
	//初始化lame的编码器
	lame_init_params(lame);

	do {
		read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
		//读出来的pcm数据放在 pcm_buffer里面
		//从pcm文件里面读PCM_SIZE个 2*sizeof(short int)个数据,放倒pcm_buffer
		if (read == 0){
			write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
		}else{
			write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

//			short *recordingData = (short *)audioData.bytes;
//			int pcmLen = audioData.length;
//			int nsamples = pcmLen / 2;
//			unsigned char buffer[pcmLen];
//
//			write = lame_encode_buffer(lame, pcm_buffer, NULL, read, mp3_buffer, MP3_SIZE);
		}
		
		count = 2+count;
		
		//3.调用方法  
		//jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);  
		
		(*env)->CallIntMethod(env, dpobj, convert, count);  
		//pcm_buffer 是pcm数据
		//read  /* number of samples per channel,
		//mp3_buffer 编码后mp3数据
		// 要写入多少个数据
		fwrite(mp3_buffer, 1, write, mp3);
		//mp3_buffer 缓冲区
		// 1是一个字节
		//write是要写的长度
		//mp3 是写入的文件名
	}while (read != 0);
	lame_close(lame);
	fclose(mp3);
	fclose(pcm);

	return 0;
}
